package cn.schoolwow.quickdao.module.database.dql.response.kit;

import cn.schoolwow.quickdao.domain.database.dql.response.PageVo;
import cn.schoolwow.quickdao.domain.database.dql.response.PagingHandler;
import cn.schoolwow.quickdao.domain.database.dql.response.Response;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.module.database.dql.parent.domain.QueryContext;
import cn.schoolwow.quickdao.module.database.dql.response.service.*;
import cn.schoolwow.quickflow.domain.FlowContext;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ResponseImpl<T> implements Response<T> {

    public QueryContext queryContext;

    public ResponseImpl(QueryContext queryContext) {
        this.queryContext = queryContext;
    }

    @Override
    public Response pagingScroll(boolean pagingScroll) {
        queryContext.responseOption.pagingScroll = pagingScroll;
        return this;
    }

    @Override
    public long count() {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new GetCountFlow())
                .putTemporaryData("queryContext", queryContext)
                .execute();
        Long count = (Long) flowContext.checkData("count");
        return count;
    }

    @Override
    public int update() {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new UpdateFlow())
                .putTemporaryData("queryContext", queryContext)
                .execute();
        int effect = (int) flowContext.checkData("effect");
        return effect;
    }

    @Override
    public int delete() {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new DeleteFlow())
                .putTemporaryData("queryContext", queryContext)
                .execute();
        int effect = (int) flowContext.checkData("effect");
        return effect;
    }

    @Override
    public T getOne() {
        List<T> list = getList();
        if (list == null || list.size() == 0) {
            return null;
        } else if(list.size()==1){
            return list.get(0);
        } else{
            throw new IllegalArgumentException("期望返回个数:1,实际返回个数:"+list.size());
        }
    }

    @Override
    public <E> E getOne(Class<E> clazz) {
        List<E> list = getList(clazz);
        if (list == null || list.size() == 0) {
            return null;
        } else if(list.size()==1){
            return list.get(0);
        } else {
            throw new IllegalArgumentException("期望返回个数:1,实际返回个数:"+list.size());
        }
    }

    @Override
    public <E> E getSingleColumn(Class<E> clazz) {
        List<E> list = getSingleColumnList(clazz);
        if (list == null || list.size() == 0) {
            return null;
        } else {
            return list.get(0);
        }
    }

    @Override
    public <E> List<E> getSingleColumnList(Class<E> clazz) {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new GetSingleColumnListCompositeBusiness())
                .putTemporaryData("queryContext", queryContext)
                .putTemporaryData("clazz", clazz)
                .execute();
        JSONArray array = (JSONArray) flowContext.getData("array");
        return array.toJavaList(clazz);
    }

    @Override
    public List getList() {
        Entity entity = queryContext.queryOption.queryTableOption.entity;
        return getList(entity.clazz);
    }

    @Override
    public <E> List<E> getList(Class<E> clazz) {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new GetListCompositeBusiness())
                .putTemporaryData("queryContext", queryContext)
                .putTemporaryData("clazz", clazz)
                .execute();
        JSONArray array = (JSONArray) flowContext.getData("array");
        return array.toJavaList(clazz);
    }

    @Override
    public PageVo<T> getPagingList() {
        return getPagingList(queryContext.queryOption.queryTableOption.entity.clazz);
    }

    @Override
    public <E> PageVo<E> getPagingList(Class<E> clazz) {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new GetPagingListCompositeBusiness())
                .putTemporaryData("queryContext", queryContext)
                .putTemporaryData("clazz", clazz)
                .execute();
        Long count = (Long) flowContext.checkData("count");
        JSONArray array = (JSONArray) flowContext.getData("array");

        PageVo pageVo = queryContext.queryOption.queryPagingOption.pageVo;
        pageVo.setArray(array);
        if(null!=clazz){
            pageVo.setList(array.toJavaList(clazz));
        }
        pageVo.setTotalSize(count);
        pageVo.setTotalPage((int) (pageVo.getTotalSize() / pageVo.getPageSize() + (pageVo.getTotalSize() % pageVo.getPageSize() > 0 ? 1 : 0)));
        pageVo.setHasMore(pageVo.getCurrentPage() < pageVo.getTotalPage());
        return pageVo;
    }

    @Override
    public <E> PageVo<E> getSingleColumnPagingList(Class<E> clazz) {
        PageVo pageVo = queryContext.queryOption.queryPagingOption.pageVo;
        pageVo.setList(getSingleColumnList(clazz));
        pageVo.setTotalSize(count());
        pageVo.setTotalPage((int) (pageVo.getTotalSize() / pageVo.getPageSize() + (pageVo.getTotalSize() % pageVo.getPageSize() > 0 ? 1 : 0)));
        pageVo.setHasMore(pageVo.getCurrentPage() < pageVo.getTotalPage());
        return pageVo;
    }

    @Override
    public JSONObject getObject() {
        JSONArray array = getArray();
        if (null == array || array.isEmpty()) {
            return null;
        }
        if(array.size()==1){
            return array.getJSONObject(0);
        }else{
            throw new IllegalArgumentException("期望返回个数:1,实际返回个数:"+array.size());
        }
    }

    @Override
    public JSONArray getArray() {
        FlowContext flowContext = queryContext.queryOption.quickFlow.startFlow(new GetArrayCompositeBusiness())
                .putTemporaryData("queryContext", queryContext)
                .execute();
        JSONArray array = (JSONArray) flowContext.getData("array");
        return array;
    }

    @Override
    public <K,V> Map<K,V> map(String key, String value, Class<K> keyClass, Class<V> valueClass) {
        JSONArray array = getArray();
        Map<K,V> map = new HashMap<>();
        for(int i=0;i<array.size();i++){
            JSONObject o = array.getJSONObject(i);
            K keyObject = o.getObject(key, keyClass);
            if(null==keyObject){
                keyObject = o.getObject(queryContext.queryOption.queryTableOption.entity.getColumnNameByFieldName(key), keyClass);
            }
            V valueObject = o.getObject(value, valueClass);
            if(null==valueObject){
                valueObject = o.getObject(queryContext.queryOption.queryTableOption.entity.getColumnNameByFieldName(value), valueClass);
            }
            map.put(keyObject, valueObject);
        }
        return map;
    }

    @Override
    public void paging(PagingHandler<T> pagingHandler){
        PageVo pageVo = queryContext.queryOption.queryPagingOption.pageVo;
        if(null==pageVo){
            throw new IllegalArgumentException("请先调用page方法指定页码和每页个数!");
        }
        int currentPage = pageVo.getCurrentPage();
        queryContext.queryOption.queryPagingOption.limit = "limit " + (pageVo.getCurrentPage() - 1) * pageVo.getPageSize() + "," + pageVo.getPageSize();
        getPagingList();
        if(!pagingHandler.pagingHandle(pageVo)){
            return;
        }
        if(queryContext.responseOption.pagingScroll){
            int totalPage = pageVo.getTotalPage();
            for(int i=currentPage+1;i<=totalPage;i++){
                pageVo.setCurrentPage(i);
                queryContext.queryOption.queryPagingOption.limit = "limit " + (pageVo.getCurrentPage() - 1) * pageVo.getPageSize() + "," + pageVo.getPageSize();
                getPagingList();
                if(!pagingHandler.pagingHandle(pageVo)){
                    return;
                }
            }
        }else{
            int totalPage = pageVo.getTotalPage();
            for(int i=0;i<totalPage;i++){
                getPagingList();
                if(!pagingHandler.pagingHandle(pageVo)){
                    return;
                }
                if(pageVo.getTotalPage()<=1){
                    break;
                }
            }
        }
    }

    @Override
    public <E> void singleColumnPaging(Class<E> clazz, PagingHandler<E> pagingHandler){
        PageVo pageVo = queryContext.queryOption.queryPagingOption.pageVo;
        if(null==pageVo){
            throw new IllegalArgumentException("请先调用page方法指定页码和每页个数!");
        }
        int currentPage = pageVo.getCurrentPage();
        queryContext.queryOption.queryPagingOption.limit = "limit " + (pageVo.getCurrentPage() - 1) * pageVo.getPageSize() + "," + pageVo.getPageSize();
        getSingleColumnPagingList(clazz);
        if(!pagingHandler.pagingHandle(pageVo)){
            return;
        }
        if(queryContext.responseOption.pagingScroll){
            int totalPage = pageVo.getTotalPage();
            for(int i=currentPage+1;i<=totalPage;i++){
                pageVo.setCurrentPage(i);
                queryContext.queryOption.queryPagingOption.limit = "limit " + (pageVo.getCurrentPage() - 1) * pageVo.getPageSize() + "," + pageVo.getPageSize();
                getSingleColumnPagingList(clazz);
                if(!pagingHandler.pagingHandle(pageVo)){
                    return;
                }
            }
        }else{
            int totalPage = pageVo.getTotalPage();
            for(int i=0;i<totalPage;i++){
                getSingleColumnPagingList(clazz);
                if(!pagingHandler.pagingHandle(pageVo)){
                    return;
                }
                if(pageVo.getTotalPage()<=1){
                    break;
                }
            }
        }
    }

    @Override
    public String toString() {
        return queryContext.toString();
    }

}
